


import ij.ImagePlus;
import ij.plugin.PlugIn;
import ij.process.ColorProcessor;
import ij.process.ImageProcessor;


import java.awt.Color;


import java.awt.Font;

import java.awt.Polygon;
import java.io.PrintStream;

import java.util.Locale;
import java.util.Random;



import pluginUtils.Circle;
import pluginUtils.CircleArrangement;
import pluginUtils.Complexe;
import pluginUtils.DoyleCircle;
import pluginUtils.MobiusTransform;
import pluginUtils.Plane;
import pluginUtils.Pos3D;
import pluginUtils.Rotation3D;
import pluginUtils.Sphere;

import pluginUtils.PackCircle;


public class AmishAutoScaleCalculSphereVersion2 extends ImagePlus implements PlugIn{
        {Locale.setDefault(Locale.US); }
       
        private ImageProcessor primeIP;
        private int X=2000,Y=2000; // image size
       
        private PrintStream output,blenderOutput;
        private double xShift=0;
        private double zShift=0;
       
       

        private Random generator=new Random(); // One always needs some randomness
       
        // For the scaling of the image
        private double x0=0,x1=1,y0=0,y1=1;
        private double acoef,ccoef,vcoef,wcoef;
       
        private String[] palette={"Yellow","Red","Blue","Green","White","NavyBlue","Turquoise","Orange"};
        private Color[] palette1={Color.YELLOW,Color.RED,Color.BLUE,Color.GREEN,Color.MAGENTA,Color.ORANGE};
        public void setCoefs(){
                acoef=X/(x1-x0);
                vcoef=Y/(y1-y0);
                ccoef=-acoef*x0;
                wcoef=-vcoef*y0;
        }
         
       
       
        public void setBounds(double xl,double xu,double yl,double yu){
                x0=xl;
                x1=xu;
                y0=yl;
                y1=yu;
        }
       
       
        private double sch=1.097; 
        private String T="T0"; 
        private String F="F0"; 
        
        private void drawCircleDecale(Circle c,double rot,Complexe cc,Complexe decale){
        	primeIP.setColor(Color.YELLOW);
            double xCenter=c.getCenter().getReal();
            double yCenter=c.getCenter().getIm();
            //if(c.getRadius()<0.001) return ;
           
            int intX=(int)((xCenter-xShift)*acoef+ccoef);
            int intY=(int)((yCenter-zShift)*vcoef+wcoef);
            int intRx=(int)(c.getRadius()*acoef);
            int intRy=(int)(c.getRadius()*vcoef);
           
           
            primeIP.drawOval(intX-intRx,intY-intRy,intRx*2,intRy*2);
           
            /*
            primeIP.moveTo(intX,intY);
            primeIP.drawString(c.getMyOrder()+"");
            */
           
            String s="torus{"+c.getRadius()+",InternRad texture{"+T+"} finish{"+F+"}\n";
           
            s+="translate<"+(decale.getReal())+",0,"+(decale.getIm())+">\n";
            s+=" rotate "+rot+"*180/pi*k*x ";  
            s+="translate <"+cc.getReal()+",0,"+cc.getIm()+">}\n";
            System.out.println(s);
            output.println(s);
            //blenderOutput.println(c.getRadius()+" "+c.getCenter().getReal()+" "+c.getCenter().getIm()+" "+rot);
   
    }
       
        private void drawCircle(Circle c,double rot,Complexe cc){
        	primeIP.setColor(Color.RED);
                double xCenter=c.getCenter().getReal();
                double yCenter=c.getCenter().getIm();
                //if(c.getRadius()<0.001) return ;
               
                int intX=(int)((xCenter-xShift)*acoef+ccoef);
                int intY=(int)((yCenter-zShift)*vcoef+wcoef);
                int intRx=(int)(c.getRadius()*acoef);
                int intRy=(int)(c.getRadius()*vcoef);
               
               
                primeIP.drawOval(intX-intRx,intY-intRy,intRx*2,intRy*2);
               
                /*
                primeIP.moveTo(intX,intY);
                primeIP.drawString(c.getMyOrder()+"");
                */
               
                String s="torus{"+c.getRadius()+",InternRad texture{"+T+"} finish{"+F+"}\n";
                s+=" rotate "+rot+"*180/pi*k*x ";  
                s+="translate <"+cc.getReal()+",0,"+cc.getIm()+">}\n";
                System.out.println(s);
                output.println(s);
                //blenderOutput.println(c.getRadius()+" "+c.getCenter().getReal()+" "+c.getCenter().getIm()+" "+rot);
       
        }
       
        private void drawPoint(Complexe c){
        	primeIP.setColor(Color.BLUE);
                double xCenter=c.getReal();
                double yCenter=c.getIm();
                int intX=(int)(xCenter*acoef+ccoef);
                int intY=(int)(yCenter*vcoef+wcoef);
                primeIP.fillOval(intX-10,intY-10,20,20);
        }
       
       
       
       
       
        private void drawLine(double xd,double yd,double xf,double yf){
                int XD=(int)(xd*acoef+ccoef);
                int YD=(int)(yd*vcoef+wcoef);
                int XF=(int)(xf*acoef+ccoef);
                int YF=(int)(yf*vcoef+wcoef);
                primeIP.drawLine(XD,YD,XF,YF);
        }
       
       
    	public String povrayCylinder(Pos3D u, Pos3D v) {
			String s="cylinder{"+u.toPovrayVector()+","+v.toPovrayVector()+",diametre texture{T0}}"; 
			return s;
		}
       
       
       
       
        public void run(String arg) {
                primeIP = new ColorProcessor(X,Y);
               
               
                double limit=5;
       
                setBounds(-limit,limit,-limit,limit);
                setCoefs();
               
               
               
               
               
               
                Polygon background=new Polygon(new int[]{0,0,X,Y},new int[]{0,X,Y,0},4);
                primeIP.setColor(Color.BLACK);
               
                primeIP.fillPolygon(background);
               
               
                primeIP.setFont(new Font(null,Font.ITALIC,60));
                primeIP.setColor(Color.WHITE);
                primeIP.setLineWidth(5);

                try{
                        output=new PrintStream("/tmp/AmishVersionTravailAutoScaleV5.txt");
                        //blenderOutput=new PrintStream("/tmp/AmishBlenderVersionTravailAutoScaleV2.txt");
                        }
                catch(Exception e){System.out.println("erreur "+e); System.exit(0); }
               
                setProcessor("Verifying", primeIP);
                
                
                int subdiv=10;
               
                Complexe origine=Complexe.createComplexeFromPolar(1*sch,0);
                
                Sphere tete=new Sphere(new Pos3D(-0.966047,0.200950,0.0),1.45);
                
                
                
                for(int i=0;i<subdiv;i++){
                	  Complexe z=Complexe.createComplexeFromPolar(1*sch,i*2*Math.PI/subdiv);
                	  double rot=i*2*Math.PI/subdiv; 
                     
                	  double dist=Complexe.distance(z, origine); 
                	  System.out.println(i+" "+dist); 
                	 
                	  
                	  if(Complexe.distance(z, origine)>0.00001){
                		  T="T1"; 
              	  		  F="F1"; 
              	  		// Le cercle de la cardioide : centre z, rayon distance(z,origine)
              	  		  Circle fromCardioid=new Circle(z,Complexe.distance(z,origine)); 
              	  		 //drawCircle(new Circle(z,Complexe.distance(z,origine)),2*i*Math.PI/subdiv,z); 
                		 if(i==3){
                			drawCircle(fromCardioid,2*i*Math.PI/subdiv,z); 
                			Pos3D OrigineDecalee=new Pos3D(sch*Math.cos(rot),0,sch*Math.sin(rot)); // equivalent a z
                	  		Rotation3D laRotation=new Rotation3D('x', rot);
                	  		Rotation3D laRotationInverse=new Rotation3D('x',-rot);
                	  		/* Equation du plan :
                	  		 * (0,-cos(rot),-sin(rot)) passant par point (sch*cos(rot),0,sch*sin(rot))
                	  		 */
                	  		// Calculer les intersections de la grosse sphere et de chacun de ces plans
                	  		Plane planLocal=new Plane(new Pos3D(0,-Math.cos(rot),-Math.sin(rot)),new Pos3D(sch*Math.cos(rot),0,sch*Math.sin(rot)));
                	  		// dessiner le plan local
                	  		output.println("plane{<"+planLocal.getA()+","+planLocal.getB()+","+planLocal.getC()+">,"+(-planLocal.getD())+" texture{pigment{color Yellow}}}");
               		  
                	  		// centre du cercle d'intersection
                	  		Pos3D H=planLocal.projectionOrthogonale(tete.getCenter());
                	  	
                	  		System.out.println("distance H plan "+planLocal.distancePoint(H)); 
                	  		System.out.println("distance origine decalee plan "+planLocal.distancePoint(OrigineDecalee));
                	  		 
                	  		//output.println(povrayCylinder(tete.getCenter(),H)); 
                	  		
                	  		// Ramener H en plan horizontal ok !!
                	  		
                	  		Pos3D HTranslate=Pos3D.sub(H,OrigineDecalee);
                	  		Pos3D HaPlat=laRotationInverse.rotate(HTranslate);
                	  		
                	  		Complexe Hap=Complexe.createComplexeFromRI(HaPlat.getX(),HaPlat.getZ()); 
                	  		
                	  		System.out.println("H "+H); 
                	  		System.out.println("Ha Plat "+HaPlat+" en complexe"+Hap); 
                	  		
                	  		// Rayon du cercle d'intersection
                	  		double disCenter=planLocal.distancePoint(tete.getCenter()); 
                	  		double rayon=tete.getRadius()*tete.getRadius()-disCenter*disCenter; 
                	  		T="T0"; 
                	  		F="F0"; 
                	  		if(rayon>=0){
                	  			System.out.println("ok ca trace"); 
                	  			rayon=Math.sqrt(rayon); 
                	  			// le cercle sur la sphere : centre Hap, rayon rayon
                	  			Circle partOfSphere=new Circle(Hap,rayon); 
                	  			System.out.println("Cercle jaune : "+partOfSphere); 
                	  			System.out.println("Cercle rouge "+fromCardioid); 
                	  			drawCircleDecale(new Circle(Hap,rayon),2*i*Math.PI/subdiv,z,Hap);
                	  			
                	  			
                	  			// Calculer les deux points d'intersection
                	  			Complexe[] inter=partOfSphere.intersection(fromCardioid);
                	  			if(inter[0]!=null){
                	  				System.out.println("racines "+inter[0]); 
                	  				System.out.println("racines "+inter[1]); 
                	  				Pos3D sol0=new Pos3D(inter[0].getReal(),0,inter[0].getIm()); 
                	  				Pos3D sol1=new Pos3D(inter[1].getReal(),0,inter[1].getIm());
                	  				drawPoint(inter[0]); 
                	  				drawPoint(inter[1]);
                	  				System.out.println("calcul 1");
                	  				System.out.println(Complexe.sub(partOfSphere.getCenter(),inter[0]).norme()); 
                	  				System.out.println(Complexe.sub(partOfSphere.getCenter(),inter[1]).norme()); 
                	  				System.out.println("calcul 2");
                	  				System.out.println(Complexe.sub(fromCardioid.getCenter(),inter[0]).norme()); 
                	  				System.out.println(Complexe.sub(fromCardioid.getCenter(),inter[1]).norme()); 
                	  				//
                	  				//sol0=Pos3D.sub(sol0, HaPlat); 
                	  				
                	  				sol0=laRotation.rotate(sol0); 
                	  				sol0=Pos3D.add(sol0, OrigineDecalee); 
                	  				//
                	  				//sol1=Pos3D.sub(sol1, HaPlat); 
                	  				
                	  				sol1=laRotation.rotate(sol1); 
                	  				sol1=Pos3D.add(sol1, OrigineDecalee);
                	  				
                	  				output.println("sphere{"+sol0.toPovrayVector()+",1.6*diametre texture{pigment{color Orange}}}"); 
                	  				output.println("sphere{"+sol1.toPovrayVector()+",1.6*diametre texture{pigment{color Orange}}}"); 
                	  			}// null
                	  		}// rayon>0
                		  
                	  		
                	  		}
                	  }
                        
                }
               
                show();
                output.close();
                System.out.println("done "); 
                
        }



	}
 